const Koa = require('koa');
const bodyParser = require('koa-bodyParser');
const json = require('koa-json');
const session = require('koa-session');
const cors = require('koa2-cors');
const jwt = require('koa-jwt')
const onerror = require('koa-onerror');
const logger = require('koa-logger');
const tokenHandler = require('./middlreware/tokenHandler')
const allConfig = require("./config");
const socketConfig = allConfig.socket;
const secret = allConfig.secret;

const index = require('./routers/index');
const user = require('./routers/user');
const live = require('./routers/live');
const chat = require('./routers/chat');
const message = require('./routers/message');
const category = require('./routers/category');

const app = new Koa();

// 跨域
app.use(cors({
	// 设置白名单
	origin: function(ctx) {
		return '*';
	},
	// 请求有效时长，单位是秒
	maxAge: 5,
	// 浏览器发送请求带上cookie
	credentials: true,
	allowMethods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
	allowHeaders: ['Content-Type', 'Accept', 'Authorization'],
}));

app.use(tokenHandler());
app.use(jwt({
	secret: secret.sign
}).unless({
	path: [/^\/user\/signIn/, /^\/user\/signUp/]
}));
app.keys = ['xiaohuan session key'];
app.use(session(app));

// 处理body和json数据
app.use(bodyParser({
	enableTypes: ['json', 'form', 'text']
}));
app.use(json());

// 路由
app.use(index.routes(), index.allowedMethods());
app.use(user.routes(), user.allowedMethods());
app.use(live.routes(), live.allowedMethods());
app.use(chat.routes(), chat.allowedMethods());
app.use(message.routes(), message.allowedMethods());
app.use(category.routes(), category.allowedMethods());

// 错误处理
onerror(app);
app.on('error', (err, ctx) => {
	console.error('server error', err, ctx);
});

// 打印日志
app.use(logger());
// 显示接口访问信息
app.use(async(ctx, next) => {
	const start = new Date();
	await next();
	const ms = new Date() - start;
	console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

// 使用socket实时服务
const server = require('http').Server(app.callback());
const io = require('socket.io')(server);
server.listen(socketConfig.PORT);
const socketHandler = require('./sockets'); //socket要实现的具体逻辑

// 注册socket连接
io.on('connection', (socket) => {
	const socketId = socket.id;
	let userId;

	// 监听用户登录
	socket.on('login', (data) => {
		// 保存用户的id和socketid
		socketHandler.saveUserSocketId(data.userId, socketId);
		userId = data.userId;
	});

	// 监听用户发私聊消息
	socket.on('sendPrivateMessage', async(data) => {
		const toUserId = data.toUserId;
		// 根据用户的id取到socketid，从而实现只对该用户推送新消息
		const socketid = await socketHandler.getUserSocketId(toUserId);
		socket.emit('receivePrivateMessage', data);
		io.to(socketid).emit('receivePrivateMessage', data);
	});

	// 监听用户发群消息
	socket.on('sendGroupMessage', (data) => {
		socket.emit('receiveGroupMessage', data);
		socket.broadcast.emit('receiveGroupMessage', data);
	});

	// 监听用户离线
	socket.on('disconnect', function() {
		// 用户离线，更新直播信息为未开播
		socketHandler.updateLiveInfoAtOffLine(userId);
	});
});

module.exports = app;